package com.codeoss.framework.view.pagebean;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.codeoss.framework.context.YunContext;
import com.codeoss.framework.converter.IConverterStore;
import com.codeoss.framework.data.metadata.Column;
import com.codeoss.framework.data.metadata.Query;
import com.codeoss.framework.data.metadata.Restrictions;
import com.codeoss.framework.data.metadata.Table;
import com.codeoss.framework.data.store.ITableStore;
import com.codeoss.framework.expression.Expression;
import com.codeoss.framework.expression.IScriptServiceStore;
import com.codeoss.framework.util.DataTypeConstants;
import com.codeoss.framework.util.StringUtils;
import com.codeoss.framework.view.clientscript.SearchDialogCallbackClientScript;
import com.codeoss.framework.view.component.IDataBindSource;
import com.codeoss.framework.view.component.IDataBinding;
import com.codeoss.framework.view.component.IDataType;
import com.codeoss.framework.view.component.IVarName;
import com.codeoss.framework.view.component.Page;
import com.codeoss.framework.view.component.Search;
import com.codeoss.framework.view.component.store.IComponentStore;
import com.codeoss.framework.view.datasource.DataSourceConfig;
import com.codeoss.framework.view.pagebean.base.BasePageBean;
import com.codeoss.framework.view.service.IVariableService;
import com.codeoss.framework.view.util.ComponentDataUtil;
import com.codeoss.framework.view.util.PageBeanUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

@Service
public class SearchViewPageBean extends BasePageBean{
	@Autowired
	private ITableStore tableStore;
	@Autowired
	private IVariableService variableService;

	public static final String KEY_SEARCH_FIELD_LIST = "key_search_field_list";

	public static final String KEY_TABLE = "key_table";

	public static final String KEY_TABLE_FIELD_LIST = "key_table_field_list";
	@Autowired
	private PageBeanUtil pageBeanUtil;
	@Autowired
	private ComponentDataUtil componentDataUtil;
	@Autowired
	private IComponentStore componentStore;
	@Autowired
	private ObjectMapper objectMapper;
	@Autowired
	private IConverterStore converterStore;
	@Autowired
	private IScriptServiceStore scriptServiceStore;
	public void beforeInit() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		if (page.isInit()) {
			return;
		}
		
		List<IDataBinding> searchDataBindingList = new ArrayList<IDataBinding>();
		pageBeanUtil.getFormFieldList(page, searchDataBindingList);
		page.setAttribute(KEY_SEARCH_FIELD_LIST, searchDataBindingList);

		pageBeanUtil.getComponent(yunContext, page, "table");
		com.codeoss.framework.view.component.Table tableComponent = (com.codeoss.framework.view.component.Table) yunContext
				.getAttribute("__component__");
		page.setAttribute(KEY_TABLE, tableComponent);

		List<IDataBinding> tableFieldList = new ArrayList<IDataBinding>();
		pageBeanUtil.getDataBindingList(tableComponent, tableFieldList);
		page.setAttribute(KEY_TABLE_FIELD_LIST, tableFieldList);

		List<String> queryColumnList = new ArrayList<String>();
		page.setAttribute(KEY_TABLE_FIELD_LIST + "_querycolumn", queryColumnList);
		for (int i = 0; i < tableFieldList.size(); i++) {
			queryColumnList.add(tableFieldList.get(i).getDataField());
		}
		page.setInit(true);
	}
	
	public void init() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		processParentPagePara();
		
		List<IDataBinding> searchDataBindingList=page.getAttribute(KEY_SEARCH_FIELD_LIST);
		for(int i=0;i<searchDataBindingList.size();i++) {
			variableService.setVariableValue(yunContext, ((IVarName)searchDataBindingList.get(i)).getVarName(), null);
		}
		pageBeanUtil.generateFormInfo(searchDataBindingList);

	

		List<String> queryColumnList=page.getAttribute(KEY_TABLE_FIELD_LIST + "_querycolumn");
		Query query = new Query();
		query.setSelectColumnList(queryColumnList);
		com.codeoss.framework.view.component.Table tableComponent=page.getAttribute(KEY_TABLE);
		if (tableComponent.isPageable()) {
			query.setLimit(tableComponent.getPageSize());
		}
		String extraSql=getSearchComponentSql();
		if(!StringUtils.isEmpty(extraSql)) {
			query.add(Restrictions.sql(extraSql));
		}
		List<IDataBinding> tableFieldList=page.getAttribute(KEY_TABLE_FIELD_LIST);
		componentDataUtil.getTableComponentData(yunContext, page, tableComponent, tableFieldList, query);
	
	}

	public void dataSearch() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page = yunContext.getPage();
		processParentPagePara();
		com.codeoss.framework.view.component.Table tableComponent=page.getAttribute(KEY_TABLE);
		Query query = new Query();
		
		List<String> queryColumnList=page.getAttribute(KEY_TABLE_FIELD_LIST+"_querycolumn");
        query.setSelectColumnList(queryColumnList);
        
		List<IDataBinding> searchDataBindingList=page.getAttribute(KEY_SEARCH_FIELD_LIST);
		for (int j = 0; j < searchDataBindingList.size(); j++) {
			IDataBinding dataBinding=searchDataBindingList.get(j);
			Object value=variableService.getVariableValue(yunContext, ((IVarName)dataBinding).getVarName());
			if(value!=null) {
				if(((IDataType)dataBinding).getDataType().equals(DataTypeConstants.DATA_TYPE_STRING)) {
					String sValue=(String)value;
					if (!StringUtils.isEmpty(sValue)) {
						String lastChar=sValue.substring(sValue.length()-1,sValue.length());
						if(lastChar.equals("%")) {
							sValue=sValue.substring(0,sValue.length()-1);
							query.add(Restrictions.like(dataBinding.getDataField(), sValue));
						}else {
							query.add(Restrictions.eq(dataBinding.getDataField(), value));	
						}
					}
				}else {
					query.add(Restrictions.eq(dataBinding.getDataField(), value));
				}
			}
		}
		query.setPage(1);
		if (tableComponent.isPageable()) {
			query.setLimit(tableComponent.getPageSize());
		}
		String extraSql=getSearchComponentSql();
		if(!StringUtils.isEmpty(extraSql)) {
			query.add(Restrictions.sql(extraSql));
		}
		String nextPage = yunContext.getViewRequest().getData().get(tableComponent.getId() + "_page");
		if (!StringUtils.isEmpty(nextPage)) {
			query.setPage(Integer.parseInt(nextPage));
		}	
		List<IDataBinding> tableFieldList=page.getAttribute(KEY_TABLE_FIELD_LIST);
		componentDataUtil.getTableComponentData(yunContext, page, tableComponent, tableFieldList, query);
	}
	
	public void dataSelected() {
		YunContext yunContext = YunContext.getCurrentContext();
		Long idValue = Long.parseLong(yunContext.getViewRequest().getData().get("id"));
		SearchDialogCallbackClientScript searchDialogCallbackClientScript=new SearchDialogCallbackClientScript();
		searchDialogCallbackClientScript.setSelectedValue(idValue);
		yunContext.addClientScript(searchDialogCallbackClientScript);
		yunContext.setRenderCompleted(true);
	}
	
	public void clearValue() {
		YunContext yunContext = YunContext.getCurrentContext();
		SearchDialogCallbackClientScript searchDialogCallbackClientScript=new SearchDialogCallbackClientScript();
		searchDialogCallbackClientScript.setSelectedValue(null);
		yunContext.addClientScript(searchDialogCallbackClientScript);
		yunContext.setRenderCompleted(true);
	}
	
	private void processParentPagePara() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page=yunContext.getPage();
		String parentCode="";
		String parentData="";
		if(!yunContext.isPostBack()) {
			parentCode=yunContext.getQueryMap().get("parentCode");
			parentData=yunContext.getQueryMap().get("parentData");
			yunContext.addPagePara("parentCode", parentCode);
			yunContext.addPagePara("parentData", parentData);
		}else {
			parentCode=yunContext.getViewRequest().getData().get(page.getId()+"_parentCode");
			parentData=yunContext.getViewRequest().getData().get(page.getId()+"_parentData");
		}
		if(parentCode==null) {
			return;
		}
		Page parentPage=componentStore.get(parentCode);
		List<IDataBinding> formDataBindingList=parentPage.getAttribute("key_form_field_list");
		if(formDataBindingList==null) {
			formDataBindingList=parentPage.getAttribute("key_search_field_list");
		}
		try {
			ObjectNode objectNode = (ObjectNode) objectMapper.readTree(parentData);
			DataSourceConfig dataSourceConfig=parentPage.getDataSourceConfigById(((IDataBindSource)formDataBindingList.get(0)).getDataSource());
			Table table=tableStore.get(dataSourceConfig.getTableName());
			for (int i = 0; i < formDataBindingList.size(); i++) {
				IDataBinding dataBinding = formDataBindingList.get(i);
				JsonNode jsonNode = objectNode.get(dataBinding.getDataField());
				if (jsonNode != null) {
					String sValue = jsonNode.asText();
					Column column = table.getColumnByColumnName(dataBinding.getDataField());
					Object value = converterStore.getConverter(column.getDataType()).convertStringToObject(sValue);
					variableService.setVariableValue(yunContext, ((IVarName)dataBinding).getVarName(), value);
				}
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}
	}
	
	private  String getSearchComponentSql() {
		YunContext yunContext = YunContext.getCurrentContext();
		Page page=yunContext.getPage();
		String parentCode="";
		String searchComponentId="";
		if(!yunContext.isPostBack()) {
			parentCode=yunContext.getQueryMap().get("parentCode");
			searchComponentId=yunContext.getQueryMap().get("searchComponent");
			yunContext.addPagePara("parentCode", parentCode);
			yunContext.addPagePara("searchComponent", searchComponentId);
		}else {
			parentCode=yunContext.getViewRequest().getData().get(page.getId()+"_parentCode");
			searchComponentId=yunContext.getViewRequest().getData().get(page.getId()+"_searchComponent");
		}
		if(parentCode==null) {
			return null;
		}
		Page parentPage=componentStore.get(parentCode);
		parentPage.findComponentById(yunContext, searchComponentId);
		Search search=(Search)yunContext.getFindComponent();
		DataSourceConfig dataSourceConfig=search.getLookupInfo().getDataSourceConfig();
		StringBuilder sql=new StringBuilder();
		Expression whereClause=dataSourceConfig.getWhereClause();
		boolean hasWhere=false;
		if(whereClause!=null) {
			String where=(String)scriptServiceStore.getScriptService(whereClause).eval(whereClause.getScript(), yunContext.getVarValueMap());
			if(!StringUtils.isEmpty(where)) {
				sql.append(where);
				hasWhere=true;
			}
		}
		Expression dynamicWhereClause=search.getLookupInfo().getDynamicWhereClauseExpression();
		if(dynamicWhereClause!=null) {
			String dynamicWhere=(String)scriptServiceStore.getScriptService(dynamicWhereClause).eval(dynamicWhereClause.getScript(), yunContext.getVarValueMap());
			if(!StringUtils.isEmpty(dynamicWhere)) {
				if(hasWhere) {
					sql.append(" and ");
				}
				sql.append(dynamicWhere);
			}
		}
		return sql.toString();
	}
	
	public void dataPage() {
		dataSearch();
	}
}
